#include"Task.hpp"

Task task;

vector<string> AllNamePipe;

class EndPoint
{
private:
  static int num;
public:
  EndPoint(int write_fd,pid_t childFd)
    :write_fd(write_fd)
    ,child_fd(childFd)
  {
    char buffer[NUM];
    snprintf(buffer,sizeof(buffer),"Process->%d[child_fd:%d,write_fd:%d]",num++,child_fd,write_fd);
    namestr = buffer;
  }
  const string GetName() const
  {
    return namestr;
  }
public:
  int write_fd;
  pid_t child_fd;
  string namestr;
};

int EndPoint::num = 0;

void WaitCommand()
{
  while(true)
  {
    int command  = 0;
    int n = read(0,&command,sizeof(int));
    if(n == 0)
    {
      cout << "父进程要我退出了" << endl;
      break;
    }
    else if(n == sizeof(int))
    {
      task.Excute(command);
    }
    else
    {
      break;
    }
  }
}

int ShowBoard()
{
  cout << "##########################    1.打印日志          ##########################" << endl;
  cout << "##########################    2.输入数据库任务    ##########################" << endl;
  cout << "##########################    3.执行网络请求      ##########################" << endl;
  cout << "##########################    4.退出              ##########################" << endl;
  cout << "请输入执行任务选项" << endl;
  int command = 0;
  cin >> command;
  return command;
}

void CtrlProcess(const vector<EndPoint>& Process)
{
  int cnt = 0;
  while(true)
  {
    int command = ShowBoard();
    if(command <= 0 || command > 4) continue;
    if(command == 4) break;
    char buffer[NUM];
    int source = cnt % 3;
    ++cnt;
    snprintf(buffer,sizeof(buffer),"进程%s执行任务%d",Process[source].GetName().c_str(),command--);
    cout << buffer << endl;
    write(Process[source].write_fd,&command,sizeof(int));
    sleep(2);
  }
}

void WaitProcess(const vector<EndPoint> Process)
{
  for(size_t i = 0; i < Process.size(); ++i)
  {
    cout << "父进程要我退出 pid : " << Process[i].child_fd << endl;
    close(Process[i].write_fd);//关闭命名管道的写端

    cout << "父进程回收子进程的僵尸状态" << endl;
    waitpid(Process[i].child_fd,nullptr,0);
  }
  for(size_t i = 0; i < AllNamePipe.size(); ++i)
  {
    cout << "回收命名管道" << AllNamePipe[i] <<endl; 
    unlink(AllNamePipe[i].c_str());
  }
}

void CreatProcess(vector<EndPoint>& Process)
{
  vector<int> fds;
  int cnt = 1;
  for(int i = 0; i < MAX; ++i)
  {
    char fifoName[NUM];//给命名管道起名字
    snprintf(fifoName,sizeof(fifoName),"%s%d",str.c_str(),cnt++);
    int NamePipeFd = mkfifo(fifoName,m);//创建命名管道
    assert(NamePipeFd != -1);
    (void)NamePipeFd;
    //if(NamePipeFd == -1) cout << errno << " " << strerror(errno) << endl;; 
    AllNamePipe.push_back(fifoName);//保存所有命名管道的名字，方便后续unlink
    pid_t fd = fork();
    if(fd == 0)//子进程
    {
      for(auto& FD : fds) close(FD);
      int read_fd = open(fifoName,O_RDONLY);//以读方式打开命名管道
      assert(read_fd != -1);
      (void)read_fd;
      dup2(read_fd,0);
      WaitCommand();
      close(read_fd);
      exit(0);
    }
    int write_fd = open(fifoName,O_WRONLY);//以写方式打开命名管道
    assert(write_fd != -1);
    (void)write_fd;
    Process.push_back(EndPoint(write_fd,fd));
    fds.push_back(write_fd);
  }
}

int main()
{
  vector<EndPoint> Process;
  
  CreatProcess(Process);

  CtrlProcess(Process);

  WaitProcess(Process);

  return 0;
}
